
package com.zcp.wizard;

import org.xmlpull.v1.XmlPullParser;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.util.Xml;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.util.ArrayList;

public class ApnUtils {

    public ApnUtils(Context context) {
        this.mContext = context;
        loadAPNs();
    }

    private Context mContext;

    public static final String TAG = "ApnManager";

    /*
     * 所有APN表的URI
     */
    public static final Uri APN_TABLE_URI = Uri.parse("content://telephony/carriers");

    /*
     * 当前APN的URI
     */
    public static final Uri PREFERRED_APN_URI = Uri.parse("content://telephony/carriers/preferapn");

    /**
     * 验证手机卡的运营商是否为移动
     * 
     * @return
     * @throws IOException
     */
    public boolean isChinaMobileNetwork() {
        boolean res = false;
        TelephonyManager tm = (TelephonyManager) mContext
                .getSystemService(Context.TELEPHONY_SERVICE);
        String operator = tm.getSimOperator();
        if (operator.equals("46000") || operator.equals("46002")) {
            res = true;
        }
        return res;
    }

    /**
     * 从资源文件中加载apn设置
     * 
     * @param context
     * @return
     */
    private String loadApnString() {

        String apnsString = "";
        TelephonyManager tm = (TelephonyManager) mContext
                .getSystemService(Context.TELEPHONY_SERVICE);
        String operator = tm.getSimOperator();
        String NUMERIC = operator;
        String MCC = operator.substring(0, 3);
        String MNC = operator.substring(3);
        InputStream in = mContext.getResources().openRawResource(R.raw.apns);
        StringBuilder sb = new StringBuilder();
        byte[] buffer = new byte[1024];
        int len = 0;
        try {
            while ((len = in.read(buffer)) != -1) {
                sb.append(new String(buffer, 0, len));
            }
            apnsString = sb.toString();
            apnsString = String.format(apnsString, NUMERIC, MCC, MNC);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return apnsString;

    }

    /**
     * 判断网络类型是否为2G，即GPRS与EDGE
     * 
     * @param context
     * @return
     */
    public static boolean is2G(Context context) {
        boolean res = false;
        TelephonyManager tm = (TelephonyManager) context
                .getSystemService(Context.TELEPHONY_SERVICE);
        int type = tm.getNetworkType();
        if (type == TelephonyManager.NETWORK_TYPE_EDGE
                || type == TelephonyManager.NETWORK_TYPE_GPRS) {
            res = true;
        }
        return res;
    }

    /**
     * 添加一个新的APN，并返回id
     */
    public int InsertAPN(ContentValues values) {
        int id = -1;
        ContentResolver resolver = mContext.getContentResolver();

        Cursor c = null;
        try {
            Uri newRow = resolver.insert(APN_TABLE_URI, values);
            if (newRow != null) {
                c = resolver.query(newRow, null, null, null, null);
                // Obtain the apn id
                int idindex = c.getColumnIndex("_id");
                c.moveToFirst();
                id = c.getShort(idindex);
            }
        } catch (SQLException e) {
            Log.d(TAG, e.getMessage());
        }

        if (c != null)
            c.close();
        return id;
    }

    public static final int APN_SATAE_UNKOWN = 0;

    public static final int APN_SATAE_CMNET = 1;

    public static final int APN_SATAE_CMWAP = 2;

    public static int getApnState(Context context) {
        ApnDAO apnDAO = getDefaultAPN(context);
        if ("cmnet".equals(apnDAO.apn)) {
            return APN_SATAE_CMNET;
        } else if ("cmwap".equals(apnDAO.apn)) {
            return APN_SATAE_CMWAP;
        } else {
            return APN_SATAE_UNKOWN;
        }
    }

    public static void toggleApn(Context context) {
        switch (getApnState(context)) {
            case APN_SATAE_CMNET:
                setDefaultAPN(context, "中国移动WAP设置", "cmwap");
                break;
            case APN_SATAE_CMWAP:
                setDefaultAPN(context, "中国移动NET设置", "cmnet");
                break;
        }
    }

    /**
     * 初始化apn
     */
    public void initApns(Context context) {
        if (isChinaMobileNetwork()) {

            clearAPNs();
            if (insertAllAPNs()) {
                setDefaultAPN(context, "中国移动NET设置", "cmnet");
            }
        }
    }

    public static ApnDAO getDefaultAPN(Context context) {
        ApnDAO apn = null;
        Cursor c = context.getContentResolver().query(PREFERRED_APN_URI, new String[] {
                "name", "apn", "_id"
        }, null, null, null);
        if (c != null) {
            if (c.moveToFirst()) {
                apn = new ApnDAO();
                apn.name = c.getString(c.getColumnIndex("name"));
                apn.apn = c.getString(c.getColumnIndex("apn"));
                apn.id = c.getInt(c.getColumnIndex("_id"));
            }
            c.close();
        }
        return apn;
    }

    /**
     * 检测手机内的APN设置与软件定义的APN是否相同，只判断apn的name属性
     * 
     * @return true存在,false不存在
     */
    public boolean checkAPNsExist() {
        boolean res = false;
        ArrayList<String> phoneApnNames = new ArrayList<String>();
        Cursor cursor = mContext.getContentResolver().query(APN_TABLE_URI, null, null, null, null);
        if (cursor != null) {
            if (cursor.moveToFirst()) {
                do {
                    String name = cursor.getString(cursor.getColumnIndex("name"));
                    phoneApnNames.add(name);
                } while (cursor.moveToNext());
            }
            if (this.apnNames.containsAll(phoneApnNames) && phoneApnNames.containsAll(apnNames)) {
                res = true;
            }
            cursor.close();
        }
        return res;
    }

    ArrayList<String> apnNames;

    ArrayList<ContentValues> apnContentValuesList;

    /**
     * 获取移动网络状态
     * 
     * @param context
     * @return true为已连接，false为未连接
     */
    public static boolean getMobileNetworkState(Context context) {
        ConnectivityManager sConnectivityManager = (ConnectivityManager) context
                .getSystemService("connectivity");
        NetworkInfo networkInfo = sConnectivityManager
                .getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
        return networkInfo.isConnected();
    }

    /**
     * 从res/raw/apns.xml中获取apn配置
     * 
     * @return ContentValues集合
     */
    private ArrayList<ContentValues> loadAPNs() {

        if (apnContentValuesList == null) {
            apnContentValuesList = new ArrayList<ContentValues>();
        }
        if (apnNames == null) {
            apnNames = new ArrayList<String>();
        }
        XmlPullParser parser = Xml.newPullParser();
        try {
            String apnsString = this.loadApnString();
            if (apnsString == null || "".equals(apnsString.trim())) {
                return null;
            }
            parser.setInput(new StringReader(apnsString));
            int event = parser.getEventType();
            ContentValues contentValues = null;
            Cursor c = mContext.getContentResolver().query(APN_TABLE_URI, null, null, null, null);
            String[] columnNames = c.getColumnNames();
            int len = columnNames.length;
            c.close();
            while (event != XmlPullParser.END_DOCUMENT) {
                switch (event) {
                    case XmlPullParser.START_TAG:
                        if (parser.isEmptyElementTag()) {
                            break;
                        }
                        if ("apnsettings".equals(parser.getName())) {
                            apnContentValuesList.clear();
                            apnNames.clear();
                        } else if ("apnsetting".equals(parser.getName())) {
                            contentValues = new ContentValues();
                        } else if ("name".equals(parser.getName())) {
                            String name = parser.nextText();
                            contentValues.put("name", name);
                            apnNames.add(name);
                        } else {
                            for (int i = 0; i < len; i++) {
                                if (columnNames[i].equals(parser.getName())) {
                                    contentValues.put(columnNames[i], parser.nextText());
                                    break;
                                }
                            }
                        }
                        break;
                    case XmlPullParser.END_TAG:
                        if ("apnsetting".equals(parser.getName())) {
                            apnContentValuesList.add(contentValues);
                            contentValues = null;
                        }
                        break;
                }
                event = parser.next();
            }
            parser = null;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return apnContentValuesList;
    }

    /**
     * 将内置的APN添加进手机
     */
    public boolean insertAllAPNs() {
        for (ContentValues cv : apnContentValuesList) {
            InsertAPN(cv);
        }
        return checkAPNsExist();
    }

    /**
     * 清除手机内的APN设置
     * 
     * @return
     */
    public boolean clearAPNs() {
        boolean res = false;
        ContentResolver resolver = mContext.getContentResolver();

        try {
            resolver.delete(APN_TABLE_URI, null, null);
            Cursor c = resolver.query(APN_TABLE_URI, null, null, null, null);
            if (c != null) {
                if (c.getCount() == 0) {
                    res = true;
                }
                c.close();
            } else {
                res = true;
            }
        } catch (SQLException e) {
            Log.d(TAG, e.getMessage());
        }
        return res;
    }

    /**
     * 根据name和apn字段获取APN的id
     * 
     * @param name
     * @param apn
     * @return
     */
    public static int getAPNid(Context context, String name, String apn) {
        int id = -1;
        Cursor c = context.getContentResolver().query(APN_TABLE_URI, null, "name=? and apn = ?",
                new String[] {
                        name, apn
                }, null);
        if (c != null) {
            if (c.moveToFirst()) {
                id = c.getInt(c.getColumnIndex("_id"));
            }
            c.close();
        }
        return id;
    }

    /*
     * 将指定id的APN设置为默认APN
     */
    public boolean setDefaultAPN(int id) {
        boolean res = false;
        ContentResolver resolver = mContext.getContentResolver();
        ContentValues values = new ContentValues();

        values.put("apn_id", id);
        try {
            resolver.update(PREFERRED_APN_URI, values, null, null);
            Cursor c = resolver.query(PREFERRED_APN_URI, new String[] {
                    "name", "apn"
            }, "_id=" + id, null, null);
            if (c != null) {
                res = true;
                c.close();
            }
        } catch (SQLException e) {
            Log.d(TAG, e.getMessage());
        }
        return res;
    }

    /*
     * 将指定id的APN设置为默认APN
     */
    public static boolean setDefaultAPN(Context context, String name, String apn) {
        int id = getAPNid(context, name, apn);
        boolean res = false;
        ContentResolver resolver = context.getContentResolver();
        ContentValues values = new ContentValues();

        values.put("apn_id", id);
        try {
            resolver.update(PREFERRED_APN_URI, values, null, null);
            Cursor c = resolver.query(PREFERRED_APN_URI, new String[] {
                    "name", "apn"
            }, "_id=" + id, null, null);
            if (c != null) {
                res = true;
                c.close();
            }
        } catch (SQLException e) {
            Log.d(TAG, e.getMessage());
        }
        return res;
    }

    /*
     * 打印所有的APN
     */
    private void EnumerateAPNs() {
        Cursor c = mContext.getContentResolver().query(APN_TABLE_URI, null, null, null, null);

        if (c != null) {
            /*
             * Fields you can retrieve can be found in
             * com.android.providers.telephony.TelephonyProvider :
             * db.execSQL("CREATE TABLE " + CARRIERS_TABLE +
             * "(_id INTEGER PRIMARY KEY," + "name TEXT," + "numeric TEXT," +
             * "mcc TEXT," + "mnc TEXT," + "apn TEXT," + "user TEXT," +
             * "server TEXT," + "password TEXT," + "proxy TEXT," + "port TEXT,"
             * + "mmsproxy TEXT," + "mmsport TEXT," + "mmsc TEXT," +
             * "type TEXT," + "current INTEGER);");
             */

            String s = "All APNs:\n";
            Log.d(TAG, s);
            try {
                s += printAllData(c); // Print the entire result set
            } catch (SQLException e) {
                Log.d(TAG, e.getMessage());
            }

            // Log.d(TAG, s + "\n\n");
            c.close();
        }

    }

    /*
     * Return all column names stored in the string array
     */
    private String getAllColumnNames(String[] columnNames) {
        String s = "Column Names:\n";
        for (String t : columnNames) {
            s += t + ":\t";
        }
        return s + "\n";
    }

    /*
     * Print all data records associated with Cursor c. Return a string that
     * contains all record data. For some weird reason, Android SDK Log class
     * cannot print very long string message. Thus we have to log
     * record-by-record.
     */
    private String printAllData(Cursor c) {
        if (c == null)
            return null;
        String s = "";
        int record_cnt = c.getColumnCount();
        Log.d(TAG, "Total # of records: " + record_cnt);

        if (c.moveToFirst()) {
            String[] columnNames = c.getColumnNames();
            Log.d(TAG, getAllColumnNames(columnNames));
            s += getAllColumnNames(columnNames);
            do {
                String row = "";
                for (String columnIndex : columnNames) {
                    int i = c.getColumnIndex(columnIndex);
                    row += c.getString(i) + ":\t";
                }
                row += "\n";
                Log.d(TAG, row);
                s += row;
            } while (c.moveToNext());
            Log.d(TAG, "End Of Records");
        }
        return s;
    }

}
